#include "pwm_api.h"

#include "wiring_private.h"
#include "pins_arduino.h"
//#include "avr/iom328p.h"
//#include "PwmName.h"

#include "wiring_private.h"
#include "pins_arduino.h"
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#include "binary.h"


#ifndef SET_REG_TCCRnX_COMxA
#define SET_REG_TCCRnX_COMxA(sfr,val) (_SFR_BYTE(sfr) |= (val))
#endif
#ifndef SET_REG_TCCRnX_COMxB
#define SET_REG_TCCRnX_COMxB(sfr,val) (_SFR_BYTE(sfr) |= (val))
#endif


#define CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(sfr)                                (_SFR_BYTE(sfr) &= (0b11111000))
#define SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_1(sfr)                                (_SFR_BYTE(sfr) |= (0b00000001))
#define SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_8(sfr)                                (_SFR_BYTE(sfr) |= (0b00000010))
#define SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_64(sfr)                               (_SFR_BYTE(sfr) |= (0b00000011))
#define SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_256(sfr)                              (_SFR_BYTE(sfr) |= (0b00000100))
#define SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_1024(sfr)                             (_SFR_BYTE(sfr) |= (0b00000101))

#define SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_1(sfr)                                (_SFR_BYTE(sfr) |= (0b00000001))
#define SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_8(sfr)                                (_SFR_BYTE(sfr) |= (0b00000010))
#define SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_64(sfr)                               (_SFR_BYTE(sfr) |= (0b00000011))
#define SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_256(sfr)                              (_SFR_BYTE(sfr) |= (0b00000100))
#define SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_1024(sfr)                             (_SFR_BYTE(sfr) |= (0b00000101))

#define SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_1(sfr)                                (_SFR_BYTE(sfr) |= (0b00000001))
#define SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_8(sfr)                                (_SFR_BYTE(sfr) |= (0b00000010))
#define SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_32(sfr)                               (_SFR_BYTE(sfr) |= (0b00000011))
#define SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_64(sfr)                               (_SFR_BYTE(sfr) |= (0b00000100))
#define SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_128(sfr)                              (_SFR_BYTE(sfr) |= (0b00000101))
#define SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_256(sfr)                              (_SFR_BYTE(sfr) |= (0b00000110))
#define SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_1024(sfr)                             (_SFR_BYTE(sfr) |= (0b00000111))




//#define SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_EXTERNAL_CLOCK_SOURCE_FALLING(sfr,val)    (_SFR_BYTE(sfr) |= (0b00000110))
//#define SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_EXTERNAL_CLOCK_SOURCE_RISING(sfr,val)     (_SFR_BYTE(sfr) |= (0b00000111))
static void pwm_update_output_mode(uint8_t _timer_nx,WaveformGenerationMode wgm)
{

    switch (wgm)
    {
    case WGM_NORMAL_TOP_0XFF                 :break;
    case WGM_PWM_PHASE_CORRECT_TOP_0XFF      :break;
    case WGM_CTC_TOP_OCRA                    :break;
    case WGM_FAST_PWM_TOP_0XFF               :
    {
        switch(_timer_nx)
        {
            #if defined(TCCR0A) && defined(COM0A1)
            case TIMER0A:
                // connect pwm to pin on timer 0, channel A
                // enable OC0A pin PWM output |  Fast PWM：0 1 1
                cbi(TCCR0B,WGM02);
                SET_REG_TCCRnX_COMxA(TCCR0A, _BV(COM0A1) |  _BV(WGM00) |  _BV(WGM01));
                break;
            #endif

            #if defined(TCCR0A) && defined(COM0B1)
            case TIMER0B:
                // connect pwm to pin on timer 0, channel B
                cbi(TCCR0B,WGM02);
                SET_REG_TCCRnX_COMxB(TCCR0A, _BV(COM0B1) |  _BV(WGM00) |  _BV(WGM01));
                break;
            #endif

            #if defined(TCCR1A) && defined(COM1A1)
            case TIMER1A:
                // connect pwm to pin on timer 1, channel A
                cbi(TCCR1B,WGM13);
                sbi(TCCR1B,WGM12);
                cbi(TCCR1A,WGM11);
                SET_REG_TCCRnX_COMxA(TCCR1A, _BV(COM1A1) |  _BV(WGM10));
                break;
            #endif

            #if defined(TCCR1A) && defined(COM1B1)
            case TIMER1B:
                // connect pwm to pin on timer 1, channel B
                cbi(TCCR1B,WGM13);
                sbi(TCCR1B,WGM12);
                cbi(TCCR1A,WGM11);
                SET_REG_TCCRnX_COMxB(TCCR1A, _BV(COM1B1) |  _BV(WGM10));
                break;
            #endif

            #if defined(TCCR2A) && defined(COM2A1)
            case TIMER2A:
                // connect pwm to pin on timer 2, channel A
                cbi(TCCR2B,WGM22);
                SET_REG_TCCRnX_COMxA(TCCR2A, _BV(COM2A1) |  _BV(WGM20) |  _BV(WGM21));
                break;
            #endif

            #if defined(TCCR2A) && defined(COM2B1)
            case TIMER2B:
                // connect pwm to pin on timer 2, channel B
                cbi(TCCR2B,WGM22);
                SET_REG_TCCRnX_COMxB(TCCR2A, _BV(COM2B1) |  _BV(WGM20) |  _BV(WGM21));
                break;
            #endif
            case NOT_ON_TIMER:
            default:break;
            
        }
    }
    break;
    case WGM_MODE_4_RESERVED                 :break;
    case WGM_PWM_PHASE_CORRECT_TOP_OCRA      :break;
    case WGM_MODE_6_RESERVED                 :break;
    case WGM_FAST_PWM_TOP_OCRA               :
    {
        switch(_timer_nx)
        {
            #if defined(TCCR0A) && defined(COM0A1)
            case TIMER0A:
                // connect pwm to pin on timer 0, channel A
                // enable OC0A pin PWM output |  Fast PWM：0 1 1
                sbi(TCCR0B,WGM02);
                SET_REG_TCCRnX_COMxA(TCCR0A, _BV(COM0A1) |  _BV(WGM00) |  _BV(WGM01));
                break;
            #endif

            #if defined(TCCR0A) && defined(COM0B1)
            case TIMER0B:
                // connect pwm to pin on timer 0, channel B
                sbi(TCCR0B,WGM02);
                SET_REG_TCCRnX_COMxB(TCCR0A, _BV(COM0B1) |  _BV(WGM00) |  _BV(WGM01));
                break;
            #endif

            #if defined(TCCR1A) && defined(COM1A1)
            case TIMER1A:
                // connect pwm to pin on timer 1, channel A
                sbi(TCCR1B,WGM12);
                sbi(TCCR1B,WGM13);
                SET_REG_TCCRnX_COMxA(TCCR1A, _BV(COM1A1) |   _BV(WGM10) |  _BV(WGM11));
                break;
            #endif

            #if defined(TCCR1A) && defined(COM1B1)
            case TIMER1B:
                // connect pwm to pin on timer 1, channel B
                sbi(TCCR1B,WGM12);
                sbi(TCCR1B,WGM13);
                SET_REG_TCCRnX_COMxB(TCCR1A, _BV(COM1B1) |  _BV(WGM10) | _BV(WGM11));
                break;
            #endif

            #if defined(TCCR2A) && defined(COM2A1)
            case TIMER2A:
                // connect pwm to pin on timer 2, channel A
                sbi(TCCR2B,WGM22);
                SET_REG_TCCRnX_COMxA(TCCR2A, _BV(COM2A1) |  _BV(WGM00) |  _BV(WGM01));
                break;
            #endif

            #if defined(TCCR2A) && defined(COM2B1)
            case TIMER2B:
                // connect pwm to pin on timer 2, channel B
                sbi(TCCR2B,WGM22);
                SET_REG_TCCRnX_COMxB(TCCR2A, _BV(COM2B1) |  _BV(WGM00) |  _BV(WGM01));
                break;
            #endif
            case NOT_ON_TIMER:
            default:break;
        }
    }
    break;
    default:break;
    }
}

/************** user invoke api:pwm_adjust_duty_cycle ******************/

void pwm_adjust_32khz_duty_cycle(uint8_t _timer_nx,float value)
{
    switch(_timer_nx)
    {
        #if defined(TCCR0A) && defined(COM0A1)
        case TIMER0A:
            // connect pwm to pin on timer 0, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_1(TCCR0B);
            OCR0A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR0A) && defined(COM0B1)
        case TIMER0B:
            // connect pwm to pin on timer 0, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_1(TCCR0B);
            OCR0B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR1A) && defined(COM1A1)
        case TIMER1A:
            // connect pwm to pin on timer 1, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_1(TCCR1B);
            OCR1A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR1A) && defined(COM1B1)
        case TIMER1B:
            // connect pwm to pin on timer 1, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_1(TCCR1B);
            OCR1B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR2A) && defined(COM2A1)
        case TIMER2A:
            // connect pwm to pin on timer 2, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_1(TCCR2B);
            OCR2A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR2A) && defined(COM2B1)
        case TIMER2B:
            // connect pwm to pin on timer 2, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_1(TCCR2B);
            OCR2B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        case NOT_ON_TIMER:
        default:break;
    }
}
void pwm_adjust_4khz_duty_cycle(uint8_t _timer_nx,float value)
{
    switch(_timer_nx)
    {
        #if defined(TCCR0A) && defined(COM0A1)
        case TIMER0A:
            // connect pwm to pin on timer 0, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_8(TCCR0B);
            OCR0A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR0A) && defined(COM0B1)
        case TIMER0B:
            // connect pwm to pin on timer 0, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_8(TCCR0B);
            OCR0B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR1A) && defined(COM1A1)
        case TIMER1A:
            // connect pwm to pin on timer 1, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_8(TCCR1B);

            OCR1A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR1A) && defined(COM1B1)
        case TIMER1B:
            // connect pwm to pin on timer 1, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_8(TCCR1B);
            OCR1B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR2A) && defined(COM2A1)
        case TIMER2A:
            // connect pwm to pin on timer 2, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_8(TCCR2B);
            OCR2A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR2A) && defined(COM2B1)
        case TIMER2B:
            // connect pwm to pin on timer 2, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_8(TCCR2B);
            OCR2B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        case NOT_ON_TIMER:
        default:break;
    }
}
void pwm_adjust_500hz_duty_cycle(uint8_t _timer_nx,float value)
{
    switch(_timer_nx)
    {
        #if defined(TCCR0A) && defined(COM0A1)
        case TIMER0A:
            // connect pwm to pin on timer 0, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_64(TCCR0B);
            OCR0A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR0A) && defined(COM0B1)
        case TIMER0B:
            // connect pwm to pin on timer 0, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_64(TCCR0B);
            OCR0B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR1A) && defined(COM1A1)
        case TIMER1A:
            // connect pwm to pin on timer 1, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_64(TCCR1B);
            OCR1A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR1A) && defined(COM1B1)
        case TIMER1B:
            // connect pwm to pin on timer 1, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_64(TCCR1B);
            OCR1B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR2A) && defined(COM2A1)
        case TIMER2A:
            // connect pwm to pin on timer 2, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_64(TCCR2B);
            OCR2A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR2A) && defined(COM2B1)
        case TIMER2B:
            // connect pwm to pin on timer 2, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_64(TCCR2B);
            OCR2B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        case NOT_ON_TIMER:
        default:break;
    }
}
void pwm_adjust_125hz_duty_cycle(uint8_t _timer_nx,float value)
{
    switch(_timer_nx)
    {
        #if defined(TCCR0A) && defined(COM0A1)
        case TIMER0A:
            // connect pwm to pin on timer 0, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_256(TCCR0B);
            OCR0A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR0A) && defined(COM0B1)
        case TIMER0B:
            // connect pwm to pin on timer 0, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_256(TCCR0B);
            OCR0B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR1A) && defined(COM1A1)
        case TIMER1A:
            // connect pwm to pin on timer 1, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_256(TCCR1B);
            OCR1A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR1A) && defined(COM1B1)
        case TIMER1B:
            // connect pwm to pin on timer 1, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_256(TCCR1B);
            OCR1B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR2A) && defined(COM2A1)
        case TIMER2A:
            // connect pwm to pin on timer 2, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_256(TCCR2B);
            OCR2A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR2A) && defined(COM2B1)
        case TIMER2B:
            // connect pwm to pin on timer 2, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_256(TCCR2B);
            OCR2B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        case NOT_ON_TIMER:
        default:break;
    }
}
void pwm_adjust_31hz_duty_cycle(uint8_t _timer_nx,float value)
{
    switch(_timer_nx)
    {
        #if defined(TCCR0A) && defined(COM0A1)
        case TIMER0A:
            // connect pwm to pin on timer 0, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_1024(TCCR0B);
            OCR0A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR0A) && defined(COM0B1)
        case TIMER0B:
            // connect pwm to pin on timer 0, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_1024(TCCR0B);
            OCR0B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR1A) && defined(COM1A1)
        case TIMER1A:
            // connect pwm to pin on timer 1, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_1024(TCCR1B);
            OCR1A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR1A) && defined(COM1B1)
        case TIMER1B:
            // connect pwm to pin on timer 1, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_1024(TCCR1B);
            OCR1B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        #if defined(TCCR2A) && defined(COM2A1)
        case TIMER2A:
            // connect pwm to pin on timer 2, channel A
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_1024(TCCR2B);
            OCR2A = (uint8_t)(value*255); // set pwm duty
            break;
        #endif

        #if defined(TCCR2A) && defined(COM2B1)
        case TIMER2B:
            // connect pwm to pin on timer 2, channel B
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_1024(TCCR2B);
            OCR2B = (uint8_t)(value*255); // set pwm duty
            break;
        #endif
        case NOT_ON_TIMER:
        default:break;
    }
}

void pwm_adjust_any_freq_duty_cycle(uint8_t _timer_nx,float value)
{
    
    switch(_timer_nx)
    {
        #if defined(TCCR0A) && defined(COM0A1)
        case TIMER0A://当前模组通道关闭
            // connect pwm to pin on timer 0, channel A
            break;
        #endif
        #if defined(TCCR0A) && defined(COM0B1)
        case TIMER0B:
            {
                uint8_t top = OCR0A;
                OCR0B = (uint8_t)(value*top); // set pwm duty
            }
            break;
        #endif

        #if defined(TCCR1A) && defined(COM1A1)
        case TIMER1A://当前模组通道关闭
            // connect pwm to pin on timer 1, channel A
            break;
        #endif
        #if defined(TCCR1A) && defined(COM1B1)
        case TIMER1B:
            {
                uint8_t top = OCR1A;
                OCR1B = (uint8_t)(value*top); // set pwm duty
            }
            break;
        #endif
        #if defined(TCCR2A) && defined(COM2A1)
        case TIMER2A://当前模组通道关闭
            // connect pwm to pin on timer 2, channel A
            break;
        #endif

        #if defined(TCCR2A) && defined(COM2B1)
        case TIMER2B:
            // connect pwm to pin on timer 2, channel B
            {
                uint8_t top = OCR2A;
                OCR2B = (uint8_t)(value*top); // set pwm duty
            }
            break;
        #endif
        case NOT_ON_TIMER:
        default:break;
    }
}

/************** user invoke api:pwm adjust freq *************/
/************** user invoke api:pwm adjust freq *************/
/************** user invoke api:pwm adjust freq *************/
static inline void pwm_update_prescalingx1_clock_select_bit(uint8_t _timer_nx,uint8_t top,float value)
{
    switch(_timer_nx)
    {
        case TIMER0B:
        {   
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_1(TCCR0B);
            OCR0A = top; // set pwm duty
            OCR0B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER1B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_1(TCCR1B);
            OCR1A = top; // set pwm duty
            OCR1B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER2B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_1(TCCR2B);
            OCR2A = top; // set pwm duty
            OCR2B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        default:break;
    }         
}
static inline void pwm_update_prescalingx8_clock_select_bit(uint8_t _timer_nx,uint8_t top,float value)
{
    switch(_timer_nx)
    {
        case TIMER0B:
        {   
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_8(TCCR0B);
            OCR0A = top; // set pwm duty
            OCR0B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER1B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_8(TCCR1B);
            OCR1A = top; // set pwm duty
            OCR1B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER2B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_8(TCCR2B);
            OCR2A = top; // set pwm duty
            OCR2B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        default:break;
    }         
}
static inline void pwm_update_prescalingx64_clock_select_bit(uint8_t _timer_nx,uint8_t top,float value)
{
    switch(_timer_nx)
    {
        case TIMER0B:
        {   
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_64(TCCR0B);
            OCR0A = top; // set pwm duty
            OCR0B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER1B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_64(TCCR1B);
            OCR1A = top; // set pwm duty
            OCR1B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER2B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_64(TCCR2B);
            OCR2A = top; // set pwm duty
            OCR2B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        default:break;
    }         
}
static inline void pwm_update_prescalingx256_clock_select_bit(uint8_t _timer_nx,uint8_t top,float value)
{
    
    switch(_timer_nx)
    {
        case TIMER0B:
        {   
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_256(TCCR0B);
            OCR0A = top; // set pwm duty
            OCR0B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER1B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_256(TCCR1B);
            OCR1A = top; // set pwm duty
            OCR1B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER2B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_256(TCCR2B);
            OCR2A = top; // set pwm duty
            OCR2B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        default:break;
    }         
}
static inline void pwm_update_prescalingx1024_clock_select_bit(uint8_t _timer_nx,uint8_t top,float value)
{
    switch(_timer_nx)
    {
        case TIMER0B:
        {   
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR0B);
            SET_REG_TCCR0B_CLOCK_SELECT_BIT_PRESCALER_1024(TCCR0B);
            OCR0A = top; // set pwm duty
            OCR0B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER1B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR1B);
            SET_REG_TCCR1B_CLOCK_SELECT_BIT_PRESCALER_1024(TCCR1B);
            OCR1A = top; // set pwm duty
            OCR1B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        case TIMER2B:
        {
            CLEAR_REG_TCCRnB_CLOCK_SELECT_BIT_PRESCALER(TCCR2B);
            SET_REG_TCCR2B_CLOCK_SELECT_BIT_PRESCALER_1024(TCCR2B);
            OCR2A = top; // set pwm duty
            OCR2B = (uint8_t)(top*value); // set pwm duty
        }
        break;
        default:break;
    }         
}
void pwm_adjust_any_freq(uint8_t _timer_nx,uint32_t freq,float value)
{
    static float top = 0;
    top = 8000000*1.0/freq;

    if(freq>=31250){
        top = (top == (uint32_t)top) ? top: (top>1?top-1:top);
        pwm_update_prescalingx1_clock_select_bit(_timer_nx,(uint8_t)top,value);
    }else if(freq>=3906){
        top = top /8;
        top = (top == (uint32_t)top) ? top: (top>1?top-1:top);
        pwm_update_prescalingx8_clock_select_bit(_timer_nx,(uint8_t)top,value);
    }else if(freq>=488){
        top = top/64;
        top = (top == (uint32_t)top) ? top: (top>1?top-1:top);
        pwm_update_prescalingx64_clock_select_bit(_timer_nx,(uint8_t)top,value);
    }else if(freq>=122){
        top = top/256;
        top = (top == (uint32_t)top) ? top: (top>1?top-1:top);
        pwm_update_prescalingx256_clock_select_bit(_timer_nx,(uint8_t)top,value);
    }else if(freq>=30){
        top = top/1024;
        top = (top == (uint32_t)top) ? top: (top>1?top-1:top);
        pwm_update_prescalingx1024_clock_select_bit(_timer_nx,(uint8_t)top,value);
    }else{
        pwm_update_prescalingx1024_clock_select_bit(_timer_nx,255,value);
    }

    pwm_update_output_mode(_timer_nx,WGM_FAST_PWM_TOP_OCRA);
}
/* fixed mode: pwm_adjust_frequency */
void pwm_adjust_frequency_32khz(uint8_t _timer_nx,float value)
{   
    //直接更改分频比1，可输出固定的32khz频率：8M/256/1 = 31.250KHZ
    pwm_adjust_32khz_duty_cycle(_timer_nx,value);
    pwm_update_output_mode(_timer_nx,WGM_FAST_PWM_TOP_0XFF);
}
void pwm_adjust_frequency_4khz(uint8_t _timer_nx,float value)
{
    //直接更改分频比8，可输出固定的4khz频率：8M/256/8 = 3.90625KHZ
    pwm_adjust_4khz_duty_cycle(_timer_nx,value);
    pwm_update_output_mode(_timer_nx,WGM_FAST_PWM_TOP_0XFF);
}
void pwm_adjust_frequency_500hz(uint8_t _timer_nx,float value)
{
    //直接更改分频比64，可输出固定的500hz频率：8M/256/64 = 488.28125HZ
    pwm_adjust_500hz_duty_cycle(_timer_nx,value);
    pwm_update_output_mode(_timer_nx,WGM_FAST_PWM_TOP_0XFF);
}
void pwm_adjust_frequency_125hz(uint8_t _timer_nx,float value)
{
    //直接更改分频比256，可输出固定的125hz频率：8M/256/256 = 122.0703125HZ
    pwm_adjust_125hz_duty_cycle(_timer_nx,value);
    pwm_update_output_mode(_timer_nx,WGM_FAST_PWM_TOP_0XFF);
}
void pwm_adjust_frequency_31hz(uint8_t _timer_nx,float value)
{
    //直接更改分频比256，可输出固定的125hz频率：8M/256/256 = 122.0703125HZ
    pwm_adjust_31hz_duty_cycle(_timer_nx,value);
    pwm_update_output_mode(_timer_nx,WGM_FAST_PWM_TOP_0XFF);
}


